#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define LEFT "["
#define RIGHT "]"
#define LABLE "# "
#define LINE_NUM 1024 
#define ARGC_SIZE 32
#define DELIM " "
#define EXITCODE 44


int lastcode = 0;

const char* getUser()
{
    return getenv("USER");
}

const char* getHostname()
{
    return getenv("HOSTNAME");
}


//const char* getPwd()
//{
//    return getenv("PWD");
//}

char pwd[LINE_NUM];

void getPwd()
{
    getcwd(pwd, sizeof(pwd));
}




// "abcd" --->  abcd\n\0
// 1. 交互信息
void interact(char* cline, int len)
{
    char* s = fgets(cline, len, stdin);
    assert(s);
    (void)s;
    
    cline[strlen(cline) - 1] = '\0';

    // printf("echo: %s", cline);
}
// 2. 分割字符串
//
int splitString(char cline[], char* _argv[])
{
        int i = 0;
       // char* ret = strtok(cline, DELIM);
       // while(ret)
       // {
       //     argv[i++] = ret;
       //     ret = strtok(NULL, DELIM);
       // }
       _argv[i++] = strtok(cline, DELIM); 
        while(_argv[i++] = strtok(NULL, DELIM));

       // argv[i] = "\0";

       // for(i=0;argv[i]; i++)
       // {
       //     printf("%d: %s\n",i, argv[i]);
       // }

        return i - 1;
        
}
// 4. 普通命令的执行
//
void  ExcuteCommand(char* _argv[])
{
    
    pid_t id = fork();
    if(id == 0)
    {
        // child
        // 进程替换， 子进程执行分割的字符串
        int ret = execvp(_argv[0], _argv);
        if(ret == -1) printf("\"%s\": command is not find!\n", _argv[0]);
        exit(EXITCODE);  
    }
    else if(id > 0) 
    {
        // parent;
        // 父进程专门进行进程等待
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if(rid == id)
        {
            lastcode = WEXITSTATUS(status);
        }
    }
    else 
    {
        perror("fork");
        return;
    }
}

// 3. 内建命令
char myenv[LINE_NUM];
int buildCommand(char* _argv[], int _argc)
{
    if(_argc == 2 && strcmp(_argv[0], "cd") == 0)
    {
        chdir(_argv[1]);
        getPwd();
        sprintf(getenv("PWD"), "%s", pwd);
        return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "export") == 0)
    {
       strcpy(myenv, _argv[1]);
       putenv(myenv);
       return 1;
    }
    else if(_argc == 2 && strcmp(_argv[0], "echo") == 0)
    {
        if(strcmp(_argv[1], "$?") == 0)
        {
            printf("%d\n", lastcode);
            lastcode = 0;
        }
        else if(*_argv[1] == '$')
        {
            char* val = getenv(_argv[1] + 1);
            if(val) printf("%s\n", val);
            else printf("%s\n", _argv[1]);
        }
        else 
        {
            printf("%s\n", _argv[1]);
        }
        return 1;
    }

    if(strcmp(_argv[0], "ls") == 0)
    {
        _argv[_argc++] = "--color";
        _argv[_argc] = NULL;
    }

    return 0;
}


int main()
{
    getPwd();
    char commandline[LINE_NUM];
    int quit = 0;
    while(!quit)
    {
        // 1. 交互信息
        printf(LEFT"%s@%s %s"RIGHT""LABLE, getUser(), getHostname(), pwd);
        interact(commandline, sizeof(commandline));
        
        // 2. 分割字符串
        char* argv[ARGC_SIZE];
        int argc = splitString(commandline, argv);
        if(argc == 0) continue;
        
        // 3. 判断指令
       int n = buildCommand(argv, argc);


        //4. 普通指令的执行
        if(!n) ExcuteCommand(argv);
        
    }
    return 0;
}
